package com.tencent.wework;

import com.example.weworkfinancesdk.utils.Platform;

import java.io.*;
import java.util.UUID;

public class FinanceFactory {

    public static void loadLibrary() throws IOException {
        removeTemporaryFiles();//参考jna

        File jnatmp = getTempDir();
        File tempDir = new File(jnatmp, UUID.randomUUID().toString());
        tempDir.mkdir();
        if (Platform.isWindows()) {
            if (Platform.is64Bit()) {
                load("libcrypto-1_1-x64", tempDir);
                load("libssl-1_1-x64", tempDir);
                load("libcurl-x64", tempDir);
                load("WeWorkFinanceSdk", tempDir);
            } else {
                load("libeay32", tempDir);
                load("ssleay32", tempDir);
                load("libcurl", tempDir);
                load("libprotobuf", tempDir);
                load("WeWorkFinanceSdk", tempDir);
            }
        } else if (Platform.isLinux()) {
            load("WeWorkFinanceSdk", tempDir);
        }
    }

    static void load(String libraryName, File tempDir) throws IOException {
        try {
            System.loadLibrary(libraryName);
        } catch (final UnsatisfiedLinkError ule1) {
            String resourceLibraryName = Platform.RESOURCE_PREFIX + "/" + System.mapLibraryName(libraryName);//File.separator windows java -jar 取不到资源
            ClassLoader loader = Thread.currentThread().getContextClassLoader();
            if (loader == null) {
                loader = Finance.class.getClassLoader();
            }
            InputStream is = loader.getResourceAsStream(resourceLibraryName);
            FileOutputStream fos = null;
            File lib = null;
            try {
                lib = new File(tempDir, System.mapLibraryName(libraryName));
                lib.deleteOnExit();
                fos = new FileOutputStream(lib);
                int count;
                byte[] buf = new byte[1024];
                while ((count = is.read(buf, 0, buf.length)) > 0) {
                    fos.write(buf, 0, count);
                }
                fos.flush();
            } catch (IOException e) {
                throw new IOException("Failed to create temporary file for " + libraryName + " library: " + e.getMessage());
            } finally {
                try {
                    is.close();
                } catch (IOException e) {
                }
                if (fos != null) {
                    try {
                        fos.close();
                    } catch (IOException e) {
                    }
                }
            }
            System.load(lib.getAbsolutePath());
            try {
                File marker = new File(lib.getParentFile(), lib.getName() + ".wechat");
                marker.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    static File getTempDir() throws IOException {
        File jnatmp;
        File tmp = new File(System.getProperty("java.io.tmpdir"));
        if (Platform.isLinux()) {
            String xdgCacheEnvironment = System.getenv("XDG_CACHE_HOME");
            File xdgCacheFile;
            if (xdgCacheEnvironment == null || xdgCacheEnvironment.trim().isEmpty()) {
                xdgCacheFile = new File(System.getProperty("user.home"), ".cache");
            } else {
                xdgCacheFile = new File(xdgCacheEnvironment);
            }
            jnatmp = new File(xdgCacheFile, "JNA/temp");
        } else {
            jnatmp = new File(tmp, "jna-" + System.getProperty("user.name").hashCode());
        }
        jnatmp.mkdirs();
        if (!jnatmp.exists()) {
            throw new IOException("JNA temporary directory '" + jnatmp + "' does not exist");
        }
        if (!jnatmp.canWrite()) {
            throw new IOException("JNA temporary directory '" + jnatmp + "' is not writable");
        }
        return jnatmp;
    }

    static void removeTemporaryFiles() throws IOException {
        File dir = getTempDir();
        FilenameFilter filter = (dir1, name) -> name.endsWith(".wechat");
        File[] files = dir.listFiles();
        for (int i = 0; files != null && i < files.length; i++) {
            File file = files[i];
            if (file.isDirectory()) {
                File[] fileArr = file.listFiles(filter);
                for (int j = 0; fileArr != null && j < fileArr.length; j++) {
                    File marker = fileArr[j];
                    String name = marker.getName();
                    name = name.substring(0, name.length() - 7);
                    File target = new File(marker.getParentFile(), name);
                    if (!target.exists() || target.delete()) {
                        marker.delete();
                    }
                }
                if (file.listFiles().length == 0) {
                    file.delete();
                }
            }
        }
    }
}
